# -*- coding: utf-8 -*-
__author__ = 'lieber'
import sys
import os
import json
import re
import jsonpath
from utils.excel import ExcelReader
from utils.myrequest import MyRequest
from utils.myassert import MyAssert
from utils.parsexml import ParseXML
from utils.log import logger

currentUrl = os.path.dirname(__file__)
parentUrl = os.path.abspath(os.path.join(currentUrl, os.pardir))
sys.path.append(parentUrl)

log = logger()


class TestcaseUtils(object):
    _my_assert = MyAssert()
    _global_params = ParseXML().global_params

    '''替换符，如果数据中包含“${}”则会被替换成公共参数中存储的数据  --  之前的有问题 \\$\\{(.*?)\\}'''
    replaceParamPattern = re.compile(r"\$\{([a-zA-Z_]+[0-9a-zA-Z_]*)\}")

    '''截取自定义方法正则表达式：__xxx(ooo)  --未验证'''
    funPattern = re.compile(r"(\_\_[a-zA-Z_]+[0-9a-zA-Z_]*\([0-9a-zA-Z_,]*\))")

    '''找到满足$.xxx格式的数据'''
    param_pattern = re.compile(r"\$\.[a-zA-Z_]+[0-9a-zA-Z_]*")

    def readtestcase2dict(self, file_name='template.xlsx'):
        if file_name == 'template.xlsx':
            file_name = os.path.join(parentUrl, "testcases", file_name)
        excel = ExcelReader(file_name, 'testcases')
        row_num = excel.row_number
        header = excel.read_row(1)
        log.info('header:%s',header)
        arrays = []
        for row in range(2, row_num + 1):
            excel_dict = {}
            for key in range(len(header)):
                excel_dict[header[key]] = excel.read_row(row)[key]
            arrays.append(excel_dict)
        log.info('excel读取到的内容如下: %s', excel_dict)
        return arrays

    def get_case_url(self, protocol, ip, port, uri):
        if protocol in ['http', 'https']:
            if port is not None and port != 'None':
                return protocol + '://' + ip + ':' + port + uri
            else:
                return protocol + '://' + ip + uri

    @staticmethod
    def get_value_bykey(self, string, str_key):
        r = re.compile(r'\'' + str_key + '["\']:\s+["\'](?P<key>[\w\d.]+)["\']')
        d = r.search(str(string))
        match_str = ''
        if d:
            match_str = d.groupdict()['key']
        return match_str

    '''
        获取需要执行的用例，读取 isvalid= "是" 的用例
    '''
    def read_case_suite(self, file_path):
        dicts = self.readtestcase2dict(file_path)
        valid_dicts = []
        for case in dicts:
            if case['isvalid'] == '是':
                valid_dicts.append(case)
        return valid_dicts

    '''
        执行用例
    '''
    def test_case(self, case):
        log.info('开始读excel')
        headers = self.update_global_params(case['headers'])
        headers = json.loads(headers) if case['headers'] else {}
        print('headers : %s', headers)
        isvalid = case['isvalid']
        url = self.update_global_params(case['url']).replace(' ', '')
        print('url is %s', url)
        protocol = url.split(':')[0]
        log.debug('url is :%s', url)
        method = case['method'].upper() if case['method'] is not None else ''
        request_data = self.update_global_params(case['request_data'])
        print('request_data is %s', request_data)
        request_data_type = case['request_data_type']
        assert_msg = case['assert_msg']
        save = case['save']
        log.debug('excel中需要保存的变量：%s', save)
        response = {}
        if method == 'SAVE' and save is not None and save != '':
            self.save_resp_params(save)
            print('当前全局变量的value为： %s', self._global_params)
            return
        if method == 'POST':
            if request_data_type == 'json':
                response = MyRequest().send_post(url=url, headers=headers, json=json.loads(request_data))
            elif request_data_type == 'data':
                response = MyRequest().send_post(url=url, headers=headers, data=request_data)
            else:
                response = MyRequest().send_post(url=url, headers=headers)
        elif method == 'GET':
            response = MyRequest().send_get(url=url, headers=headers)
        try:
            if assert_msg is not None and assert_msg != '':
                res_json = response.json()
                self.verify_result(res_json, assert_msg)
        except ValueError:
            print('response is not a json format str : %s', response.text)
            self._my_assert.my_assert(response, assert_msg)
        log.debug('接口请求完成')
        print("【request请求的response内容为：%s】" % response.text)
        if save is not None and save != '':
            self.save_resp_params(save, response.json())
            print('当前全局变量的value为： %s', self._global_params)

    '''
        提取response json串中的值保存至公共池中
        @resp_json 接口返回的json字符串
        @excel_allSave  从excel里面读取的需要保存的变量
    '''
    def save_resp_params(self, excel_save_params, resp_json=''):
        log.info('开始调用发送请求后，保存变量的方法。')
        excel_save_params_array = excel_save_params.split(';')
        for excel_param in excel_save_params_array:
            log.debug(excel_param)
            pattern = re.compile(r"([^;=]*)=([^;]*)")
            m = pattern.match(excel_param)
            log.info('匹配到的参数为%s', m.group())
            if m:
                key = self.get_keyorvalue_from_res(resp_json, m.group(1))
                log.info('key替换没报错')
                value = self.get_keyorvalue_from_res(resp_json, m.group(2))
                log.info('value替换完了')
                self._global_params[key] = value
                log.debug("存储公共参数   %s值为：%s.", key, value)
        log.debug('最后的所有变量为：%s', self._global_params)

    '''
        从接口返回值中获取某个key的value保存成变量
        匹配$. 开头的变量,返回key，否则，返回key对应的value
    '''
    def get_keyorvalue_from_res(self, resp_json, key):
        log.info('get_keyorvalue_from_res()方法,key 为 %s', key)
        m = self.funPattern.match(key)  # 截取自定义方法正则表达式：__xxx(ooo)
        #if m is None:
        #    return key
        if key.startswith("$."):
            print('key:%s', key)
            key = jsonpath.jsonpath(resp_json, key)  # 取获取到的第一个，不然会报错
            log.info('截取自定义方法正则表达式：$.xxx')
            print('key:%s', key)
            key = str(key[0])
        elif m:
            print('这个下面的代码还没有调试，没想好场景')
            args = m.group(2)
            print('args is %s', args)
            argArr = args.split(",")
            for index in range(len(argArr)):
                arg = argArr[index]
                if arg.startsWith("$."):
                    argArr[index] = jsonpath.jsonpath(resp_json, arg)
            value = 1 # FunctionUtil.getValue(m.group(1), argArr)
            key = self.replace_first(key, m.group(), value)
        return key


    '''
        @param source_str 待替换字符串
        @param match_str  匹配字符串
        @param replace_str  目标替换字符串
    '''
    def replace_first(self, source_str, match_str,  replace_str):
        index = source_str.indexOf(match_str)
        mat_length = len(match_str)
        sour_length = len(source_str)
        begin_str = source_str[0, index]
        end_str = source_str[index + mat_length, sour_length]
        source_str = begin_str + replace_str + end_str
        return source_str


    '''
        更新excel中引用的全局变量的字段值 (替换excel请求数据中包含“${}”)
    '''
    def update_global_params(self, param):
        log.info('开始替换参数')
        if param == '' or param is None:
            return ''
        replace_keys = self.replaceParamPattern.findall(param)
        log.info('replace_keys: %s', replace_keys)
        for replace_key in replace_keys:
            log.info('replace_key:  %s', replace_key)
            # 从公共参数池中获取值
            value = self.get_global_value_by_key(replace_key)
            param = param.replace('${' + replace_key + '}', value)
        log.debug('参数替换完成')
        return param

    def get_global_value_by_key(self, key):
        if key == '' or key not in self._global_params.keys():
            return ''
        else:
            return self._global_params[key]

    def verify_result(self, resp_json, verify_str):
        verify_str = self.update_global_params(verify_str)
        log.debug("期望结果：" + verify_str);
        pattern = re.compile(r"([^;]*)=([^;]*)")
        m = pattern.match(verify_str)
        if m:
            actual_value = self.get_keyorvalue_from_res(resp_json, m.group(1))
            except_value = self.get_keyorvalue_from_res(resp_json, m.group(2))
            assert actual_value == except_value, "value '{}' != '{}'".format(actual_value, except_value)
        else:
            print('断言有问题')
